#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "string.h"
#include "driver/gpio.h"
#include "MySpiffs.h"

#include "esp_spiffs.h"

static const char *TAG = "spiffsTag";

void init_spiffs() 
{
    ESP_LOGI(TAG, "init SPIFFS");
    
    esp_vfs_spiffs_conf_t conf = {
        .base_path = "/spiffs",
        .partition_label = NULL,
        .max_files = 5,          // 最大打开文件数
        .format_if_mount_failed = true
    };
    
    // 挂载文件系统
    esp_err_t ret = esp_vfs_spiffs_register(&conf);
    if (ret != ESP_OK) {
        if (ret == ESP_FAIL) {
            ESP_LOGE(TAG, "register failed");
        } else if (ret == ESP_ERR_NOT_FOUND) {
            ESP_LOGE(TAG, "cannot found spiiffs area");
        } else {
            ESP_LOGE(TAG, "init failed (%s)", esp_err_to_name(ret));
        }
        return;
    }
    
    size_t total = 0, used = 0;
    ret = esp_spiffs_info(NULL, &total, &used);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "get spiffs information failed (%s)", esp_err_to_name(ret));
    } else {
        ESP_LOGI(TAG, "area size: all=%d, used=%d", total, used);
    }
}

// 写入文件
void write_file(const char *path, const char *data) 
{
    ESP_LOGI(TAG, "write file: %s", path);
    
    FILE *f = fopen(path, "w");
    if (f == NULL) {
        ESP_LOGE(TAG, "open file failed");
        return;
    }
    
    fprintf(f, "%s", data);
    fclose(f);
}

// 读取文件
void read_file(const char *path) 
{
    ESP_LOGI(TAG, "read file: %s", path);
    
    FILE *f = fopen(path, "r");
    if (f == NULL) {
        ESP_LOGE(TAG, "open file failed");
        return;
    }
    
    char line[128];
    while (fgets(line, sizeof(line), f) != NULL) {
        printf("%s", line);
    }
    uart_write_bytes(UART_NUM_0, line, strlen(line));
    fclose(f);
}

#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>

void list_spiffs_directory(const char *base_path) {
    DIR *dir;
    struct dirent *entry;
    struct stat stat_buf;
    char path[512];

    if ((dir = opendir(base_path)) == NULL) {
        perror("opendir");
        return;
    }

     ESP_LOGI(TAG, "Listing directory: %s\n", base_path);
    
    while ((entry = readdir(dir)) != NULL) {
        // 跳过当前目录和上级目录
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        // 构建完整路径
        snprintf(path, sizeof(path), "%s/%s", base_path, entry->d_name);

        // 获取文件信息
        if (stat(path, &stat_buf) == -1) {
            perror("stat");
            continue;
        }

        // 打印文件/目录信息
         ESP_LOGI(TAG, "%-40s\t", path);
        if (S_ISDIR(stat_buf.st_mode)) {
            printf("[DIR]\n");
            // 递归列出子目录
            list_spiffs_directory(path);
        } else {
             ESP_LOGI(TAG, "[FILE] Size: %ld bytes\n", stat_buf.st_size);
        }
    }

    closedir(dir);
}

// 初始化路径数组
void init_path_array(PathArray *array, int initial_capacity) {
    array->paths = (char **)malloc(initial_capacity * sizeof(char *));
    array->count = 0;
    array->capacity = initial_capacity;
}

// 添加路径到数组
static void add_path(PathArray *array, const char *path) {
    if (array->count >= array->capacity) {
        // 扩容
        array->capacity *= 2;
        array->paths = (char **)realloc(array->paths, array->capacity * sizeof(char *));
    }
    
    array->paths[array->count] = strdup(path); // 复制字符串
    array->count++;
}

// 释放路径数组
static void free_path_array(PathArray *array) {
    for (int i = 0; i < array->count; i++) {
        free(array->paths[i]);
    }
    free(array->paths);
    array->count = 0;
    array->capacity = 0;
}

// 递归遍历目录并存储路径
void store_paths_recursive(PathArray *array, const char *base_path) {
    DIR *dir;
    struct dirent *entry;
    struct stat stat_buf;
    char path[512];

    if ((dir = opendir(base_path)) == NULL) {
        perror("opendir");
        return;
    }

    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        snprintf(path, sizeof(path), "%s/%s", base_path, entry->d_name);
        add_path(array, path);

        if (stat(path, &stat_buf) == -1) {
            perror("stat");
            continue;
        }

        if (S_ISDIR(stat_buf.st_mode)) {
            store_paths_recursive(array, path);
        }
    }

    closedir(dir);
}

void delete_file(const char *filepath) 
{
    // 检查文件是否存在
    if (access(filepath, F_OK) != 0) {
        printf("文件不存在: %s\n", filepath);
        return;
    }

    // 删除文件
    if (unlink(filepath) == 0) {
        printf("成功删除文件: %s\n", filepath);
    } else {
        perror("删除文件失败");
    }
}